﻿Public Class DateDifference

    Private ReadOnly parts_ As IList(Of Long)

    Public Sub New(
        ByVal d1 As Date,
        ByVal d2 As Date,
        ByVal ParamArray divisions() As TimeSpan)

        Dim interval = d1.Subtract(d2)
        Dim result As New List(Of Long)
        For Each division In divisions
            Dim chunks = interval.Ticks \ division.Ticks
            result.Add(chunks)
            Dim substraction = TimeSpan.FromTicks(chunks * division.Ticks)
            Debug.Assert(interval >= substraction)
            interval = interval.Subtract(substraction)
        Next
        parts_ = result
    End Sub

    Public Sub New(ByVal parts As IList(Of Long))
        parts_ = parts
    End Sub

    Private Shared Function CheckPart(ByRef part As Long, ByVal singFormat As String, ByVal plurFormat As String, ByVal result As List(Of String), ByRef level As Integer) As Boolean
        If part = 0 Then
        ElseIf part = 1 Then
            result.Add(String.Format(singFormat, part))
            level -= 1
        Else
            result.Add(String.Format(plurFormat, part))
            level -= 1
        End If
        Return level = 0
    End Function

    Public Function Format(
        ByVal singularFormats As IEnumerable(Of String),
        ByVal pluralFormats As IEnumerable(Of String),
        ByVal maxLevels As Integer,
        ByVal delimiter As String) As String

        Dim result As New List(Of String)
        Dim level = maxLevels

        For i = 0 To parts_.Count - 1
            If CheckPart(parts_(i), singularFormats(i), pluralFormats(i), result, level) Then Return Join(result.ToArray, delimiter)
        Next
        Return Join(result.ToArray, delimiter)
    End Function

    Default Public ReadOnly Property Part(ByVal index As Integer) As Long
        Get
            Return Me.parts_(index)
        End Get
    End Property

End Class